/*
 * Copyright (c) 2022, Chongqing UCchip InfoTech Co.,Ltd
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-12-21     jlu          the first version
 */
#include "uc_hex.h"
#include "uc_log.h"
#include "rtthread.h"

/**
 * @brief  16进制编码
 *
 * @param  dst 输出编码字符串
 * @param  src 输入字符串
 * @param  len 输入字符串长度
 * @return 成功返回0
 * @note   输出字符串长度为 2 * len + 1
 */
int hex_encode(char *dst, const char *src, int len)
{
    char hi, lo;
    for (int i = 0; i < len; ++i)
    {
        hi = (src[i] >> 4) & 0x0F;
        lo = src[i] & 0x0F;
        dst[i * 2] = ((hi > 9) ? 55 : 48) + hi;
        dst[i * 2 + 1] = ((lo > 9) ? 55 : 48) + lo;
    }
    dst[len * 2] = '\0';
    return 0;
}

/**
 * @brief  16进制解码
 *
 * @param  dst 输出解码字符串
 * @param  src 输入字符串
 * @param  len 输入字符串长度
 * @return 成功返回0，失败放回非0
 * @note   输出字符串长度为 len / 2 + 1
 */
int hex_decode(char *dst, const char *src, int len)
{
    char ch1, ch2, hi, lo;
    for (int i = 0; i < len; i += 2)
    {
        ch1 = src[i];
        ch2 = src[i + 1];
        // 如果属于 ['0', '9']
        if (ch1 >= '0' && ch1 <= '9')
            hi = ch1 & 0x0F;
        else
        {
            // 大写转换
            ch1 &= 0xDF;
            // 如果属于 ['A', 'F']
            if (ch1 >= 'A' && ch1 <= 'F')
                hi = ch1 - 55;
            else
                return 1;
        }
        // 如果属于 ['0', '9']
        if (ch2 >= '0' && ch2 <= '9')
            lo = ch2 & 0x0F;
        else
        {
            // 大写转换
            ch2 &= 0xDF;
            // 如果属于 ['A', 'F']
            if (ch2 >= 'A' && ch2 <= 'F')
                lo = ch2 - 55;
            else
                return 1;
        }
        // 合并为16进制
        dst[i >> 1] = (hi << 4) | lo;
    }
    dst[len >> 1] = '\0';
    return 0;
}

/**
 * @brief  Hex 解码
 *
 * @param  dst 输出字符串
 * @param  dst_len 输出字符串长度
 * @param  src 输入字符串
 * @param  src_len 输入字符串长度
 * @return 成功返回0，否则返回非0
 * @note   输出字符串需使用 rt_free 释放
 */
int string_hex_decode(char **dst, int *dst_len, const char *src, int src_len)
{
    *dst_len = (src_len + 1) >> 1;
    *dst = rt_malloc(*dst_len + 1);
    if (RT_NULL == *dst)
    {
        TRACE_E("%s, %d malloc failed", __FUNCTION__, __LINE__);
        return -1;
    }
    if (hex_decode(*dst, src, src_len))
    {
        TRACE_E("%s, %d hex_decode failed", __FUNCTION__, __LINE__);
        dst_len = 0;
        return -2;
    }
    return 0;
}